import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
import expressionParser from 'docxtemplater/expressions.js'
import jsPDF from "jspdf";
import html2canvas from "html2canvas";

/**
 * 导出TXT的方法
 * @param fileName 生成txt的文件名
 * @param data 导出需要的数据
 */
export const exportTxt = (fileName: string, data: string) => {
    const blob = new Blob([data], { type: "text/plain;charset=utf-8" });
    const filename = `${fileName}.txt`;
    const link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    link.download = filename;
    link.click();
    window.URL.revokeObjectURL(link.href);
}

/**
 * 导出Word的方法
 * @param template 自配的模板名称，默认放在public中
 * @param data 导出需要的数据
 * @param fileName 生成word的文件名
 */
export const exportWordDocx = (template: string, data: any, fileName: string) => {
    // 读取并获得模板文件的二进制内容
    function loadFile(url: string, callback: (error: any, content: any) => void) {
        PizZipUtils.getBinaryContent(url, callback);
    }
    // demo.docx是模板。我们在导出的时候，会根据此模板来导出对应的数据
    loadFile(template, function (
        error: Error | null,
        content
    ) {
        // 抛出异常
        if (error) {
            throw error;
        }
        // 创建一个JSZip实例，内容为模板的内容
        const zip: PizZip = new PizZip(content);
        const doc: Docxtemplater = new Docxtemplater().loadZip(zip).setOptions({
            paragraphLoop: true,
            linebreaks: true,
            parser: expressionParser,
        }) as Docxtemplater;
        // 设置模板变量的值
        doc.setData(data);
        try {
            // 用模板变量的值替换所有模板变量
            doc.render();
        } catch (error: any) {
            //抛错
            throw error;
        }
        // 生成一个代表docxtemplater对象的zip文件（不是一个真实的文件，而是在内存中的表示）
        const out = doc.getZip().generate({
            type: "blob",
            mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        });
        // 将目标文件对象保存为目标类型的文件，并命名
        saveAs(out, `${fileName}.docx`);
    });

}

/**
 * 导出PDF的方法
 * @param DOM 需要转换为pdf的dom
 * @param offset 图片高度偏移量，解决分页将文字分裂的问题
 * @param fileName 生成pdf的文件名
 */
export const exportPdf = async (DOM: HTMLElement | null, offset: number = 30, fileName: string = 'content') => {
    // const pdf = new jsPDF('p', 'mm', 'a4')

    const cavans = await html2canvas(DOM!, {
        windowHeight: DOM!.scrollHeight,
        windowWidth: DOM!.scrollWidth,
        scale: 3,
        useCORS: true,
    })
    let contentWidth = cavans.width
    let contentHeight = cavans.height
    //一页pdf显示html页面生成的canvas高度;
    let pageHeight = contentWidth / 592.28 * 841.89
    //生成pdf的html页面高度
    let leftHeight = contentHeight
    //页面偏移
    let position = 0
    //a4纸的尺寸[595.28,841.89]，html页面生成的canvas在pdf中图片的宽高
    let imgWidth = 595.28
    let imgHeight = (592.28 / contentWidth * contentHeight) - offset
    // canvas.crossOrigin="anonymous";
    let pageData = cavans.toDataURL('image/jpeg', 1.0);

    let PDF = new jsPDF('p', 'pt', 'a4')
    //有两个高度需要区分，一个是html页面的实际高度，和生成pdf的页面高度(841.89)
    //当内容未超过pdf一页显示的范围，无需分页
    if (leftHeight < pageHeight) {
        PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
    } else {
        while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight
            position -= 841.89
            if (leftHeight > 0) {
                //避免添加空白页
                PDF.addPage()
            }
        }
    }
    PDF.setFontSize(20);
    PDF.save(`${fileName}.pdf`)
}

/**
 * 导出图片的方法
 * @param DOM 需要转换为图片的dom
 * @param fileName 生成图片的文件名
 */
export const exportImg = (DOM: HTMLElement | null, fileName: string) => {
    let opts = {
        useCORS: true,
        //backgroundColor: "transparent", //去掉白边
        backgroundColor: "#fff",//背景透明
        scrollX: 0,
        scrollY: 0,
        dpi: window.devicePixelRatio,
        height: DOM!.scrollHeight,
        windowHeight: DOM!.scrollHeight
    };
    html2canvas(DOM!, opts).then((canvas) => {
        var imgUrl = canvas.toDataURL("image/png", 1); // 获取生成的图片的url
        const image = new Image();
        // 解决跨域 Canvas 污染问题
        image.setAttribute("crossOrigin", "anonymous");
        image.src = imgUrl;
        image.onload = () => {
            const canvas = document.createElement("canvas");
            canvas.width = image.width;
            canvas.height = image.height;
            const context = canvas.getContext("2d")!;
            context.drawImage(image, 0, 0, image.width, image.height);
            canvas.toBlob(async (blob: any) => {
                const url = URL.createObjectURL(blob);
                saveAs(url, `${fileName}.jpg`)
            });
        };
    });
}